var Bookshelf = require('bookshelf');

var db = Bookshelf.initialize({
	client: 'sqlite3',
	connection: {
		filename: './db.sqlite'
	}
});

var actions = {
    'get':    {method:'GET'},
    'save':   {method:'POST'},
    'query':  {method:'GET', isArray:true},
    'remove': {method:'DELETE'},
    'delete': {method:'DELETE'}
};

function extend(src, target) {
    /**
     * 采用这种迂回的方式在于model.attributes不是一个继承自Object的对象（由Object.create(null)创建)
     * 在对其应用angular.extend时遍历key时会报错，因为它没有hasOwnProperty方法
     * 故在这里相当于重新弄出了一个Object对象
     * 注：new Object(model.attributes)无效
     */
    if (!target.hasOwnProperty) {
        target = JSON.parse(JSON.stringify(target));
    }
    angular.extend(src, target);
}



angular.module("bsResource", ['ng']).
/**
 * 其实这就是ngResource的一个代理，增强了ResourceFacotry生成的Resource的功能
 */
    factory('ResourceFactory', function($rootScope) {
        return function(tableName) {
            var RawResource = db.Model.extend({
            	tableName: tableName
            });

            var RawResourceCollection = db.Collection.extend({
            	model: RawResource
            });

            function collection2models(collection) {
                return collection.models.map(function(model){
                    return new Resource(model.attributes);
                });
            }

            var Resource = function(json) {
                extend(this, json);
            };

            // 类上的方法
            angular.extend(Resource, {
            	"get": function(cfg, success, failure) {
            		(new RawResourceCollection()).query({where: cfg})
                        .fetch()
            		    .then(function(collection){
                            success(collection2models(collection));
                            $rootScope.$apply();
            		});

            	},
                "setupPage": function(config) {
                    var config = angular.extend({
                        "page": 0,
                        "page.size": 10,
                        "page.sort": "id",
                        "page.sort.dir": "asc"
                    }, config);

                    return {
                        query: function (params, success, error) {
                            var cfg = {};
                            //如果params不是函数，则认为它是配置
                            if (!angular.isFunction(params)) {
                                angular.extend(cfg, config, params);
                            } else {
                                //否则认为params=>success, success则为error
                                angular.extend(cfg, config);
                                var temp = success;
                                success = params;
                                error = temp;
                            }

                            return Resource.query(cfg, success, error);

                        }
                    }
                }
            });
            Resource.query = Resource.get;

            // instance上的方法
            angular.extend(Resource.prototype, {
               "$get": function(success, failure) {
                   Resource.get({id: this.id}, success, failure);
               },
               "$save": function (sucess, failure) {
                   var me = this;
                   new RawResource(this).save().then(function(model){
                       extend(me, model.attributes);
                       sucess && sucess(this);
                   });
               },
               "$remove": function (sucess, failure) {
                   new RawResource({id: this.id}).destroy().then(function(){
                       sucess && sucess();
                   });
               },
               "$set": function(params, success, failure) {
                   var me = this;
                   new RawResource({id: this.id})
                       .save(params, {patch: true})
                       .then(function(model) {
                          extend(me, model.attributes);
                          success && success(me);
                   });

               },
               "detach": function(list) {
                   for(var i = 0; i < list.length; i++) {
                       if (list[i]['id'] === this.id) {
                           list.splice(i, 1);
                           return;
                       }
                   }
               }
            });

            Resource.prototype.$delete = Resource.prototype.$remove;

            /**
             * 对于$set方法，仅当设置到服务成功才更新本地变量.
             * 为params增加一个_keys属性，表示仅设置params中提到的key

            Resource.prototype['$set'] = function(params, success, error) {
                var me = this;
                var new_obj = angular.extend({}, this, params);
                new_obj.__keys = _.keys(params);
                var result = Resource.save(null, new_obj, function(data){
                    angular.extend(me, data); //only after success, we apply the new value to the origin object
                    success && success.apply(this, arguments);
                }, error);
                return result.$promise || result;
            };
             */

            Resource.setupPage = function(config){
                var config = angular.extend({
                    "page": 0,
                    "page.size": 10,
                    "page.sort": "id",
                    "page.sort.dir": "asc"
                }, config);

                return {
                    query: function (params, success, error) {
                        var cfg = {};
                        //如果params不是函数，则认为它是配置
                        if (!angular.isFunction(params)) {
                            angular.extend(cfg, config, params);
                        } else {
                            //否则认为params=>success, success则为error
                            angular.extend(cfg, config);
                            var temp = success;
                            success = params;
                            error = temp;
                        }

                        return Resource.query(cfg, success, error);

                    }
                }
            }/* End of Resource.setupPage */

            return Resource;
        }

    });